<template>
  <a-flex vertical :gap="'middle'">
    <Bubble.List
      :roles="roles"
      :style="{ maxHeight: '300px' }"
      :items="messages.map(({ id, message, status }) => ({
        key: id,
        // loading: status === 'loading',
        role: status === 'local' ? 'local' : 'ai',
        content: message,
      }))"
    />
    <Sender
      :loading="senderLoading"
      :value="content"
      @change="setContent"
      @submit="handleSubmit"
    />
  </a-flex>
</template>

<script setup>
import { ref, h } from 'vue'
import { UserOutlined } from '@ant-design/icons-vue'
import { Bubble, Sender, useXAgent, useXChat } from 'ant-design-x-vue'
import sysConfig from '@/config'
import tool from '@/utils/tool'

defineOptions({
  name: 'BubbleChat'
})

// 配置参数
const BASE_URL = 'http://127.0.0.1:82'
const PATH = '/chat/completions'
const MODEL = 'gpt-3.5-turbo'

// 获取token
const token = tool.data.get('TOKEN')

const roles = {
  ai: {
    placement: 'start',
    avatar: { icon: h(UserOutlined), style: { background: '#fde3cf' } },
    typing: { step: 5, interval: 20 },
    style: {
      maxWidth: '600px',
    },
  },
  local: {
    placement: 'end',
    avatar: { icon: h(UserOutlined), style: { background: '#87d068' } },
  },
}

const mockSuccess = ref(false)
const content = ref('')
const senderLoading = ref(false)

const setContent = (v) => {
  content.value = v
}

// Agent for request
const [agent] = useXAgent({
  baseURL: BASE_URL + PATH,
  model: MODEL,
  request: async ({ message }, { onUpdate, onSuccess, onError }) => {
    try {
      senderLoading.value = true
      const response = await fetch(`${BASE_URL}${PATH}`, {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
          'Accept': 'text/event-stream',
          'token': sysConfig.TOKEN_PREFIX + token
        },
        body: JSON.stringify({
          messages: [{ role: 'user', content: message }],
          model: MODEL,
          stream: true
        }),
      })

      const reader = response.body?.getReader()
      if (!reader) {
        throw new Error('Failed to get response reader')
      }

      let result = ''
      while (true) {
        const { done, value } = await reader.read()
        if (done) {
          console.log('Stream reading completed, final result:', result)
          onSuccess(result)
          break
        }
        const chunk = new TextDecoder().decode(value)
        console.log('Received chunk:', chunk)
        // 处理SSE数据格式
        const lines = chunk.split('\n')
        for (const line of lines) {
          if (line.trim() === '') {
            console.log('Skipping empty line')
            continue
          }
          if (line.startsWith('data:')) {
            const jsonStr = line.slice(5).trim()
            // 跳过空数据行
            if (!jsonStr) {
              console.log('Skipping empty data line')
              continue
            }
            // 处理完成信号
            if (jsonStr === '[DONE]') {
              console.log('Received [DONE] signal')
              continue
            }
            try {
              console.log('Processing SSE data:', jsonStr)
              const jsonData = JSON.parse(jsonStr)
              if (jsonData.choices?.[0]?.delta?.content) {
                result += jsonData.choices[0].delta.content
                onUpdate(result)
              } else {
                console.log('Skipping chunk without content')
              }
            } catch (e) {
              if (jsonStr) {
                console.error('Failed to parse SSE data:', e.message)
                console.debug('Raw data:', jsonStr)
              }
            }
          } else {
            console.log('Skipping non-data line:', line)
          }
        }
      }
    } catch (error) {
      onError(error)
    } finally {
      senderLoading.value = false
    }
  },
})

// Chat messages
const { onRequest, messages } = useXChat({
  agent: agent.value,
  requestPlaceholder: 'Waiting...',
  requestFallback: 'Mock failed return. Please try again later.',
})

const handleSubmit = (nextContent) => {
  onRequest(nextContent)
	// 获取上文所有消息
	console.log(messages.value)
  setContent('')
}
</script>
